package com.canaan.business.controller.pc.api.erp;

import cn.hutool.core.util.ObjectUtil;
import cn.hutool.json.JSONUtil;
import com.canaan.business.common.enums.inOutStock.OutOrderStatusEnum;
import com.canaan.business.domain.basic.ErpProduct;
import com.canaan.business.domain.bill.*;
import com.canaan.business.domain.vo.GoodsVo;
import com.canaan.business.domain.vo.OutStockCallbackVo;
import com.canaan.business.domain.vo.OutStockCreateVo;
import com.canaan.business.service.basic.IErpProductService;
import com.canaan.business.service.bill.*;
import com.canaan.common.annotation.ApiInterfaceLog;
import com.canaan.common.core.controller.BaseController;
import com.canaan.common.core.domain.AjaxResult;
import com.canaan.common.encrypt.AesCryptorUtils;
import com.canaan.common.encrypt.ApiResult;
import com.canaan.common.encrypt.ResultDTO;
import com.canaan.common.utils.DateUtils;
import com.canaan.common.utils.StringUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

@Slf4j
@Api(tags = "出库")
@RestController
@RequestMapping("")
public class OutStockController extends BaseController {
    @Resource
    private IAdjustOutBillService adjustOutBillService;
    @Resource
    private IAdjustOutBillDetailService adjustOutBillDetailService;
    @Resource
    private IPurchaseReturnBillService purchaseReturnBillService;
    @Resource
    private IPurchaseReturnBillDetailService purchaseReturnBillDetailService;
    @Resource
    IModulationOutBillService modulationOutBillService;
    @Resource
    IModulationOutBillDetailService modulationOutBillDetailService;

    @Resource
    IErpProductService productService;

    @Resource
    HttpCommonReq commonReq;

    /**
     * 出库创建
     */
    @ApiOperation(value = "出库创建(EDI)")
    @ApiInterfaceLog(title = "出库创建(EDI)")
    @PostMapping("/edi/outStock/ediCreate")
    public String ediCreate(HttpServletRequest request) {
        try {
            String requirementOrderReqJsonStr = commonReq.getCommonReq(request).getData();
            log.info("出库创建请求参数：{}", requirementOrderReqJsonStr);
            OutStockCreateVo outStockCreateVo = JSONUtil.toBean(requirementOrderReqJsonStr, OutStockCreateVo.class);
            String result = handleOutnStockCreate(outStockCreateVo);
            log.info("出库创建返回结果：{}", result);
            return buildResult(true, result);
        } catch (Exception e) {
            log.error("创建入库需求单异常,msg:{}", e.getMessage(), e);
            return buildResult(false, e.getMessage());
        }
    }

    /**
     * 出库创建
     */
    @ApiOperation(value = "出库创建")
    @ApiInterfaceLog(title = "出库创建")
    @PostMapping("/erp/outStock/create")
    public AjaxResult wmsCreate(@RequestBody OutStockCreateVo outStockCreateVo) {
        handleOutnStockCreate(outStockCreateVo);
        return success();
    }

    /**
     * 出库回调
     */
    @ApiOperation(value = "出库回调")
    @ApiInterfaceLog(title = "出库回调")
    @PostMapping("/erp/outStock/callback")
    public AjaxResult callback(@RequestBody OutStockCallbackVo outStockCallbackVo) {
        return success();
    }

    /**
     * 处理出库创建
     *
     * @param outStockCreateVo 出库创建对象
     * @return
     */
    @Transactional
    public String handleOutnStockCreate(OutStockCreateVo outStockCreateVo) {
        //TODO  采购⼊库单 DIPI 11    对应采购收货单   表名 wms_receive_product_bill wms_receive_product_bill_detail
        //      取消发货单 DIPI 31    不对应单据表,所有单据的取消都需要调用此接口  WMS需要判断是否已经在执行中,如果在执行中,则不允许取消
        //      采购退供 DORS 23      对应入库退货单   wms_purchase_return_bill wms_purchase_return_bill_detail
        //      调拨单⼊库单 DITRS 14  对应调拨入库单   wms_adjust_in_bill  wms_adjust_in_bill_detail
        //      调拨单出库单 DOTRS 24  对应调拨出库单   wms_adjust_out_bill wms_adjust_out_bill_detail
        //      出库调整单 DOWOO 22    不对应单据,可以新增单据表保存, 仅仅是调整出库数量
        //      ⼊库调整单 DIWOI 15    不对应单据,可以新增单据表保存, 仅仅是调整入库数量
        String result = "未找到此类型单据";
        boolean isSuccess = true;
        switch (outStockCreateVo.getBusinessType()) {     //根据业务类型调用对应接口
            case 31:
                //取消发货单 DIPI 2
                //TODO 调用WMS取消发货单接口
                break;
            case 23:
                handlePurchaseReturnBill(outStockCreateVo);
                result = "采购退供创建成功";
                break;
            case 24:
                handleAdjustOutBill(outStockCreateVo);
                result = "调拨出库单创建成功";
                break;
            case 22:
                handleModulationInBill(outStockCreateVo);
                result = "出库调整单创建成功";
                break;
            default:
                log.error("业务类型错误,业务类型:{}", outStockCreateVo.getBusinessType());
                isSuccess = false;
                break;
        }
        if (!isSuccess) {
            throw new RuntimeException("出库业务类型错误,业务类型:" + outStockCreateVo.getBusinessType());
        }
        return result;
    }

    /**
     * 采购退供
     *
     * @param outStockCreateVo 出库创建
     */
    private void handlePurchaseReturnBill(OutStockCreateVo outStockCreateVo) {
        PurchaseReturnBill bill = purchaseReturnBillService.selectPurchaseReturnBillByNo(outStockCreateVo.getBizNo());
        if (ObjectUtil.isNotEmpty(bill)) {
            logger.error("存在相同单据：{}", outStockCreateVo.getBizNo());
            return;
        }
        PurchaseReturnBill purchaseReturnBill = new PurchaseReturnBill();
        purchaseReturnBill.setNo(outStockCreateVo.getBizNo());
        purchaseReturnBill.setStockCode(outStockCreateVo.getStockCode());
        purchaseReturnBill.setOwner(outStockCreateVo.getOwner());
        purchaseReturnBill.setStockStatus(outStockCreateVo.getStockStatus().toString());
        purchaseReturnBill.setArrivalDate(DateUtils.parseDate(outStockCreateVo.getArrivalDate()));
        purchaseReturnBill.setShortMatch(outStockCreateVo.getShortMatch().toString());
        purchaseReturnBill.setRemark(outStockCreateVo.getRemark());
        purchaseReturnBill.setStatus(OutOrderStatusEnum.NEW.getCode());
        if(ObjectUtil.isNotEmpty(outStockCreateVo.getTargetInfo())) {
            purchaseReturnBill.setCellCode(outStockCreateVo.getTargetInfo().getCellCode());
        }
        //明细保存
        for (GoodsVo goodDetail : outStockCreateVo.getGoodDetails()) {
            PurchaseReturnBillDetail detail = new PurchaseReturnBillDetail();
            detail.setNo(outStockCreateVo.getBizNo());
            detail.setOrderNo(outStockCreateVo.getBizNo());
            detail.setProductNo(goodDetail.getCode());
            ErpProduct product = productService.selectErpProductByProductNo(goodDetail.getCode());
            if (product != null) {
                detail.setProductName(product.getProductName());
            }
            Long num = Long.valueOf(goodDetail.getNum());
            detail.setOrderQty(num);
            detail.setProductUnit(goodDetail.getUnit());
            detail.setBatchNo(goodDetail.getBatchNo());
            detail.setCreateBy("ERP");
            purchaseReturnBillDetailService.insertPurchaseReturnBillDetail(detail);
        }
        purchaseReturnBill.setCreateBy("ERP");
        purchaseReturnBillService.insertPurchaseReturnBill(purchaseReturnBill);
    }

    /**
     * 调拨出库单
     *
     * @param outStockCreateVo 出库创建
     */
    private void handleAdjustOutBill(OutStockCreateVo outStockCreateVo) {
        //调拨单出库单 DOTRS 5
        //TODO 调用调拨出库单创建接口
        AdjustOutBill bill = adjustOutBillService.selectAdjustOutBillByNo(outStockCreateVo.getBizNo());
        if (ObjectUtil.isNotEmpty(bill)) {
            logger.error("存在相同单据：{}", outStockCreateVo.getBizNo());
            return;
        }
        //主表保存
        AdjustOutBill adjustOutBill = new AdjustOutBill();
        adjustOutBill.setNo(outStockCreateVo.getBizNo());
        adjustOutBill.setStockCode(outStockCreateVo.getStockCode());
        adjustOutBill.setOwner(outStockCreateVo.getOwner());
        adjustOutBill.setStockStatus(outStockCreateVo.getStockStatus().toString());
        adjustOutBill.setArrivalDate(DateUtils.parseDate(outStockCreateVo.getArrivalDate()));
        adjustOutBill.setShortMatch(outStockCreateVo.getShortMatch().toString());
        adjustOutBill.setRemark(outStockCreateVo.getRemark());
        adjustOutBill.setStatus(OutOrderStatusEnum.NEW.getCode());
        adjustOutBill.setCheckTotalQty(0L);
        if(ObjectUtil.isNotEmpty(outStockCreateVo.getTargetInfo())) {
            adjustOutBill.setAddress(outStockCreateVo.getTargetInfo().getCellCode());
        }
        Long total = 0l;
        //明细保存
        for (GoodsVo goodDetail : outStockCreateVo.getGoodDetails()) {
            AdjustOutBillDetail adjustOutBillDetail = new AdjustOutBillDetail();
            adjustOutBillDetail.setBillNo(outStockCreateVo.getBizNo());
            adjustOutBillDetail.setProductNo(goodDetail.getCode());
            ErpProduct product = productService.selectErpProductByProductNo(goodDetail.getCode());
            if (product != null) {
                adjustOutBillDetail.setProductName(product.getProductName());
            }
            Long num = Long.valueOf(goodDetail.getNum());
            adjustOutBillDetail.setQty(num);
            adjustOutBillDetail.setReceivedQty(0L);
            adjustOutBillDetail.setProductUnit(goodDetail.getUnit());
            adjustOutBillDetail.setBatchNo(goodDetail.getBatchNo());
            adjustOutBillDetail.setCreateBy("ERP");
            total += num;
            adjustOutBillDetailService.insertAdjustOutBillDetail(adjustOutBillDetail);
        }
        adjustOutBill.setCreateBy("ERP");
        adjustOutBill.setTotalQty(total);
        adjustOutBillService.insertAdjustOutBill(adjustOutBill);
    }

    /**
     * 处理入库调整单
     *
     * @param outStockCreateVo 出创建
     */
    private void handleModulationInBill(OutStockCreateVo outStockCreateVo) {
        //出库调整单 DOWOO 6
        //TODO 调用出库调整单创建接口
        ModulationOutBill bill = modulationOutBillService.selectModulationOutBillByNo(outStockCreateVo.getBizNo());
        if (ObjectUtil.isNotEmpty(bill)) {
            logger.error("存在相同单据：{}", outStockCreateVo.getBizNo());
            return;
        }
        ModulationOutBill modulationOutBill = new ModulationOutBill();
        modulationOutBill.setBizNo(outStockCreateVo.getBizNo());
        modulationOutBill.setStockCode(outStockCreateVo.getStockCode());
        modulationOutBill.setOwner(outStockCreateVo.getOwner());
        modulationOutBill.setRemark(outStockCreateVo.getRemark());
        modulationOutBill.setStockStatus(outStockCreateVo.getStockStatus().toString());
        modulationOutBill.setStatus(OutOrderStatusEnum.NEW.getCode());
        if(ObjectUtil.isNotEmpty(outStockCreateVo.getTargetInfo())) {
            modulationOutBill.setCellCode(outStockCreateVo.getTargetInfo().getCellCode());
        }
        if(ObjectUtil.isNotEmpty(outStockCreateVo.getShortMatch())){
            modulationOutBill.setShortMatch(outStockCreateVo.getShortMatch().toString());
        }
        Long total = 0l;
        //子表入库
        for (GoodsVo detail : outStockCreateVo.getGoodDetails()) {
            ModulationOutBillDetail modulationOutBillDetail = new ModulationOutBillDetail();
            modulationOutBillDetail.setBizNo(outStockCreateVo.getBizNo());
            modulationOutBillDetail.setProductNo(detail.getCode());
            ErpProduct product = productService.selectErpProductByProductNo(detail.getCode());
            if (product != null) {
                modulationOutBillDetail.setProductName(product.getProductName());
            }
            Long num = Long.valueOf(detail.getNum());
            modulationOutBillDetail.setQty(num);
            modulationOutBillDetail.setProductUnit(detail.getUnit());
            modulationOutBillDetail.setBatchNo(detail.getBatchNo());
            modulationOutBillDetail.setCreateBy("ERP");
            total += num;
            modulationOutBillDetailService.insertModulationOutBillDetail(modulationOutBillDetail);
        }
        modulationOutBill.setTotalQty(total);
        modulationOutBill.setCreateBy("ERP");
        modulationOutBillService.insertModulationOutBill(modulationOutBill);
    }

    /**
     * 生成返回结果
     *
     * @param hasSuccess
     * @return
     */
    private static String buildResult(boolean hasSuccess, String defaultMsg) {
        ApiResult<ResultDTO<AjaxResult>> result = new ApiResult<>();
        ResultDTO<AjaxResult> resultDTO = new ResultDTO<>();
        AjaxResult ajaxResult = new AjaxResult();
        if (hasSuccess) {
            resultDTO.setStatus("success");
            ajaxResult.success();
        } else {
            resultDTO.setStatus("fail");
            ajaxResult.error(defaultMsg);
        }
        result.setContent(resultDTO);
        resultDTO.setData(ajaxResult);

        return AesCryptorUtils.encrypt(JSONUtil.toJsonStr(result), AesCryptorUtils.SECURITY_KEY);
    }
}
